#include "SocketChannel.h"
#include "common.h"
#include "utils.h"
#ifdef _WIN32
#include <WinSock2.h>
#include <time.h>
#define _TIMESPEC_DEFINED
#else
#include <sys/socket.h>
#include <netinet/in.h> /*for struct sockaddr_in*/
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/tcp.h>
#endif

SocketChannel::SocketChannel() {
	fd = 0;
	socketType = 0;
}
SocketChannel::~SocketChannel() {
}
int SocketChannel::connectChannel(int isTcp, const char* host, int port,
		int recvTimeout) {
	fd = 0;
	socketType = 0;
	socketType = isTcp;
	sockaddr_in m_server_addr;
	int m_localSocket;
	if ((m_localSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		LOGW("new m_localSocket fail [%s:%d]", host, port);
		return m_localSocket;
	}
	LOGI("CTcpSocket:CTcpSocket [%s:%d]", host, port);
	fd = m_localSocket;
	m_server_addr.sin_family = AF_INET;
	m_server_addr.sin_port =htons(port);
	char ip[30];
	host2Ip(host, ip, 30);
	m_server_addr.sin_addr.s_addr = inet_addr(ip);
	int connectResult = connect(m_localSocket,
			(struct sockaddr*) &m_server_addr, sizeof(m_server_addr));
	if (connectResult < 0) {
		LOGW("TCP connect  %s error [%s],%d\n", host, strerror(errno), errno);
		return connectResult;
	} else {
		LOGI("Connect %s success", host);
	}
#ifdef _WIN32
	unsigned long ul=1;
	int r = ioctlsocket(m_localSocket, FIONBIO, &ul);
	if (r == SOCKET_ERROR)
	{
		return false;
	}
#endif
#ifndef _WIN32
	LOGI("set recv timeout %d ", recvTimeout);
	struct timeval timeout = { recvTimeout, 0 };

	if (setsockopt(m_localSocket, SOL_SOCKET, SO_RCVTIMEO, (void *) &timeout,
			sizeof(struct timeval)) < 0) {
		LOGW("TCP set recv timeout fail [%s],%d", strerror(errno), errno);
	}
#endif

#ifndef _WIN32
	int optval = 1;
	if (setsockopt(m_localSocket, IPPROTO_TCP, TCP_NODELAY, &optval,
			sizeof(optval)) < 0) {
		LOGW("TCP set NODELAY failed %s,%d", strerror(errno), errno);
	}
	// turn off SIGPIPE signal
//		int nRet = -1;
//	#if (__APPLE__ || __MACH__) //Defined by GNU C and Intel C++
//		nRet = setsockopt(m_localSocket, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
//	#else
//		nRet = setsockopt(m_localSocket, SOL_SOCKET, MSG_NOSIGNAL, &optval, sizeof(optval));
//	#endif
//		if (nRet < 0)
//		{
//			LOGW("TCP set ignore sig_pip failed ", strerror(errno), errno);
//		}
#endif//
	return 0;
}
void SocketChannel::close() {
#ifdef _WIN32
#define SHUT_RDWR  SD_BOTH
#endif
	if (shutdown(fd, SHUT_RDWR) < 0) {
		//成功则返回0，错误返回-1，错误码errno：
		//  EBADF表示sockfd不是一个有效描述符；
		//	ENOTCONN表示sockfd未连接；
		//	ENOTSOCK表示sockfd是一个文件描述符而不是socket描述符。
		LOGE("shut down socket %s", strerror(errno));
	}

//	windows closesocket(...)
//	linux close(...)
}


int SocketChannel::peek(char* buf, int maxSize){
	return recv(fd,buf, maxSize, MSG_PEEK|MSG_DONTWAIT);
}
int SocketChannel::recvData(char* buf, int lenWantToRecv) {
	bool iscontinue = false;
	int recved  = 0;
	do{
		recved = recv(fd,buf, lenWantToRecv, MSG_DONTWAIT);
		if (recved <= 0) {
			if (errno == EINTR) {
				LOGW("SOCKET INT Signal:  error(%s),[%d]", strerror(errno),
						errno);
			}else{
				LOGE("recv error(%s),[%d]", strerror(errno), errno);
			}
		}else{
			iscontinue = false;
		}
	}while(iscontinue);


//			if (nRecv == 0)
//			{
//				LOGI("**************** recv 0:  Close By The Server ***");
//			}
//			if (EAGAIN == errno || EWOULDBLOCK == errno)
//				return nReadBytes;
//}
	return recved;
}
int SocketChannel::sendData(const char* buf, int size) {
	return (int) send(fd, buf, size, 0);;
}

